package com.tt.expandableadapter;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.BaseAdapter;

import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;

/**
 * 可展开的适配器 <功能简述> <Br>
 * <功能详细描述> <Br>
 * 
 * @author Kyson
 */
public abstract class ExpandableAdapter<T> extends BaseAdapter {

    protected List<T> mDatas = new ArrayList<T>();
    protected Context mContext;
    protected LayoutInflater mInflater;
    private int mLayoutRes;
    private int mAboveRes;
    private int mExpandRes;
    //展开的item 位置
    protected int mExpandedPosition = -1;

    //展开的view
    private View mExpandView = null;

    public ExpandableAdapter(Context context, int layoutRes, int aboveRes,
            int expandRes) {
        this.mContext = context;
        mInflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.mLayoutRes = layoutRes;
        this.mAboveRes = aboveRes;
        this.mExpandRes = expandRes;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = (ViewGroup) mInflater.inflate(mLayoutRes, parent,
                    false);
            viewHolder.aboveContainer = (ViewGroup) convertView
                    .findViewById(mAboveRes);
            viewHolder.expandContainer = (ViewGroup) convertView
                    .findViewById(mExpandRes);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        View aboveV = getAboveView(position, viewHolder.above,
                viewHolder.aboveContainer);
        if (viewHolder.aboveContainer.getChildCount() > 0) {
            viewHolder.aboveContainer.removeAllViews();
        }
        viewHolder.aboveContainer.addView(aboveV);

        View expandV = getExpandView(position, viewHolder.expand,
                viewHolder.expandContainer);
        if (viewHolder.expandContainer.getChildCount() > 0) {
            viewHolder.expandContainer.removeAllViews();
        }
        viewHolder.expandContainer.addView(expandV);

        if (mExpandView == convertView && mExpandedPosition != position) {
            //View的物理地址相同，而记录的position不同
            //说明view被回收了
            //重要！
            mExpandView = null;
        }
        if (mExpandedPosition == position) {
            viewHolder.expandContainer.setVisibility(View.VISIBLE);
            mExpandView = convertView;
        } else {
            viewHolder.expandContainer.setVisibility(View.GONE);
        }
        viewHolder.aboveContainer.setOnClickListener(new ExpandOnClickListener(
                convertView, position));
        return convertView;
    }

    public class ExpandOnClickListener implements OnClickListener {

        private View mConvertView;

        private int mPosition;

        public ExpandOnClickListener(View view, int position) {
            this.mConvertView = view;
            this.mPosition = position;
        }

        @Override
        public void onClick(View v) {
            if (mExpandedPosition == mPosition) {
                close(getExView(mConvertView));
                mExpandView = null;
                mExpandedPosition = -1;
            } else {
                close(getExView(mExpandView));
                open(getExView(mConvertView));
                //                mExpandView = mConvertView;
                mExpandedPosition = mPosition;
            }
        }
    }

    /**
     * 根据convertview得到展开的view <功能简述>
     * 
     * @param cv
     * @return
     */
    private static View getExView(View cv) {
        if (cv == null) {
            return null;
        }
        ViewHolder viewHolder = (ViewHolder) cv.getTag();
        return viewHolder.expandContainer;
    }

    private static int getHeight(View view) {
        final int widthSpec = View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED);
        final int heightSpec = View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED);
        view.measure(widthSpec, heightSpec);
        return view.getMeasuredHeight();
    }

    /**
     * 展开菜单 <功能简述>
     */
    private void open(final View view) {
        if (view == null) {
            return;
        }
        view.setVisibility(View.VISIBLE);
        int start = view.getLayoutParams().height < 0 ? 0 : view
                .getLayoutParams().height;
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start,
                getHeight(view));
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                int currentValue = (Integer) animator.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
                layoutParams.height = currentValue;
                view.setLayoutParams(layoutParams);
            }
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                notifyDataSetChanged();
            }
        });
        valueAnimator.setDuration(500).start();
    }

    /**
     * 收起菜单 <功能简述>
     */
    private void close(final View view) {
        if (view == null) {
            return;
        }
        view.setVisibility(View.VISIBLE);
        int start = view.getLayoutParams().height < 0 ? 0 : view
                .getLayoutParams().height;
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start, 0);
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                int currentValue = (Integer) animator.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
                layoutParams.height = currentValue;
                view.setLayoutParams(layoutParams);
            }
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                notifyDataSetChanged();
            }
        });
        valueAnimator.setDuration(500).start();
    }

    protected abstract View getAboveView(int position, View convertView,
            ViewGroup parent);

    protected abstract View getExpandView(int position, View convertView,
            ViewGroup parent);

    public static class ViewHolder {
        ViewGroup aboveContainer;
        ViewGroup expandContainer;
        View above;
        View expand;
    }

    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public T getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public void setList(List<T> list) {
        this.mDatas = list;
    }

}
